<template>
  <div id="addQuestionPage">
    <h1>编辑题目列表</h1>

    <el-form label-width="100px" class="formLoading">
      <el-form-item label="应用 id" prop="id">
        <el-input :value="appId" clearable disabled />
      </el-form-item>
      <el-form-item label="题目 id" prop="id">
        <el-input :value="oldQuestionVO?.id" clearable disabled />
      </el-form-item>

      <!-- 题目列表 -->
      <el-form-item label="题目列表" prop="appDesc">
        <!-- 在最上方添加题目 -->
        <el-button type="primary" plain size="default" class="addOnTopButton" @click="addQuestion(0)">
          {{ questionList.length < 1 ? "添加题目" : "在最上方插入题目" }} </el-button>

            <!-- 单个题目 -->
            <el-form label-width="100px" v-for="(question, questionIndex) in questionList" class="questionItem">
              <!-- 题目标题 (编号从 1 开始) -->
              <el-form-item :label="`题目 ${questionIndex + 1} 标题`" prop="id">
                <el-input v-model="question.title" clearable placeholder="请输入题目标题" />
              </el-form-item>

              <!-- 题目选项 -->
              <el-form-item :label="`题目 ${questionIndex + 1} 选项`" prop="id">
                <!-- 在最上方添加选项 -->
                <el-button type="primary" plain size="default" @click="addQuestionOption(question, 0)">
                  {{ question.options!.length < 1 ? "添加选项" : "在最上方插入选项" }} </el-button>

                    <!-- 题目选项列表 -->
                    <el-form ref="formRef" label-width="100px" v-for="(option, optionIndex) in question.options">
                      <!-- 单个题目选项 -->
                      <el-form-item :label="`选项 ${optionIndex + 1}`" prop="id">
                        <!-- 单个题目选项的所有属性 -->
                        <el-form ref="form" label-width="100px">
                          <el-form-item label="选项名">
                            <el-input v-model="option.key" clearable placeholder="请输入选项名" />
                          </el-form-item>
                          <el-form-item label="选项值">
                            <el-input v-model="option.value" clearable placeholder="请输入选项值" />
                          </el-form-item>
                          <el-form-item label="选项结果" v-if="appVO?.appType == AppTypeEnum.QUESTION">
                            <el-input v-model="option.result" clearable placeholder="请输入选项结果" />
                          </el-form-item>
                          <el-form-item label="选项得分">
                            <el-input v-model.number="option.score" clearable placeholder="请输入选项得分" />
                          </el-form-item>
                          <!-- 题目选项操作按钮 -->
                          <el-form-item label="选项操作">
                            <el-button type="primary" plain size="default"
                              @click="addQuestionOption(question, optionIndex + 1)">
                              在下方插入选项
                            </el-button>
                            <el-button type="danger" plain size="default"
                              @click="deleteQuestionOption(question, optionIndex)">
                              删除当前选项
                            </el-button>
                          </el-form-item>
                        </el-form>
                      </el-form-item>
                    </el-form>
              </el-form-item>

              <!-- 题目操作按钮 -->
              <el-form-item :label="`题目 ${questionIndex + 1} 操作`">
                <el-button type="primary" plain size="default" @click="addQuestion(questionIndex + 1)">
                  在下方插入题目
                </el-button>
                <el-button type="danger" plain size="default" @click="deleteQuestion(questionIndex)">
                  删除当前题目
                </el-button>
              </el-form-item>
            </el-form>
      </el-form-item>
    </el-form>

    <!-- 底部按钮 -->
    <div class="buttonWrapper">
      <el-button type="info" plain size="default" class="submitButton" @click="router.back">
        返回
      </el-button>
      <el-button type="primary" size="default" @click="doSubmit" class="submitButton" :loading="submitButtonIsLoading">
        提交
      </el-button>
      <el-button type="primary" size="default" @click="dialogFormVisible = true" class="submitButton">
        使用 AI 生成题目
      </el-button>
      <el-button type="info" plain size="default" @click="router.push({ name: '编辑评分策略', params: { appId } })"
        class="submitButton" v-if="appVO?.scoringStrategy !== ScoringStrategyEnum.AI">
        前往设置评分策略
      </el-button>
    </div>
  </div>

  <!-- AI 生成题目的 dialog -->
  <el-dialog v-model="dialogFormVisible" width="500">
    <template #header="{ close, titleId, titleClass }">
      <h3 :id="titleId">
        使用
        <a href="https://www.zhipuai.cn/" target="_blank" style="text-decoration: none;">智谱 AI</a>
        创建题目
      </h3>
    </template>
    <el-form :model="aiGenerateQuestionForm">
      <el-form-item label="生成题目个数 (1 ~ 10)">
        <el-input v-model="aiGenerateQuestionForm.questionNumber" autocomplete="off" type="number" min="1" max="10"
          oninput="if (value > 10) value = 10; if (value < 1) value = 1" />
      </el-form-item>
      <el-form-item label="每题选项个数 (2 ~ 6)">
        <el-input v-model="aiGenerateQuestionForm.optionNumber" autocomplete="off" type="number" min="2" max="6"
          oninput="if (value > 6) value = 6; if (value < 1) value = 1" />
      </el-form-item>
    </el-form>

    <!-- 进度条 -->
    <div class="progressWrapper">
      <el-progress :class="aiGenerateButtonLoading ? '' : 'invisible'"
        :percentage="Math.ceil(aiGeneratedQuestionNumber / aiGenerateQuestionForm.questionNumber! * 100)"
        :stroke-width="10" show-text striped striped-flow />
    </div>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="dialogFormVisible = false">返回</el-button>
        <el-button type="primary" @click="doAiGenerateQuestions" :loading="aiGenerateButtonLoading">开始生成</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { getAppVoByIdUsingGet } from '@/api/appController';
import { addQuestionUsingPost, editQuestionUsingPost, listQuestionVoByPageUsingPost } from '@/api/questionController';
import { AppTypeEnum, ResponseCodeEnum, ScoringStrategyEnum, SqlSortOrderEnum } from '@/enums';
import { ElLoading, ElMessage } from 'element-plus';
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';

const router = useRouter();

// 获取 appId
const { appId } = defineProps(["appId"]);

// 应用信息
const appVO = ref<API.AppVO>();

// 题目列表
const questionList = ref<API.QuestionContentDTO[]>([]);

// 已有的题目 VO
const oldQuestionVO = ref<API.QuestionVO>();

// 挂载时, 根据 appId 去后台获取题目列表
onMounted(async () => {
  // 为表单添加加载效果
  const loading = ElLoading.service({
    // target 用 css 选择器即可
    target: ".formLoading",
    lock: true,
    text: "加载中...",
  });

  // 获取应用信息
  const appResult = await getAppVoByIdUsingGet({
    id: appId
  })

  // 赋值给表单
  if (appResult.data.code === ResponseCodeEnum.SUCCESS && appResult.data.data) {
    appVO.value = appResult.data.data;
  } else {
    ElMessage.error("获取应用数据失败: " + appResult.data.message);
  }

  // 查询得到该应用的最新题目列表 (1 条记录)
  const questionResult = await listQuestionVoByPageUsingPost({
    appId,
    current: 1,
    pageSize: 1,
    sortField: "createTime",
    sortOrder: SqlSortOrderEnum.DESC,
  });

  // 尝试获取已有题目
  if (questionResult.data.code === ResponseCodeEnum.SUCCESS && questionResult.data.data?.records) {
    oldQuestionVO.value = questionResult.data.data?.records[0];
    // 因为当题目不存在时 records 是空数组, 所以这里要判断一下, 否则会报错
    if (oldQuestionVO.value) {
      questionList.value = oldQuestionVO.value.questionContent ?? [];
    }
  } else {
    ElMessage.error("获取题目列表失败: " + questionResult.data.message);
  }

  // 解除表单加载状态
  loading.close();
});

/**
 * 添加题目
 * @param index
 */
const addQuestion = (index: number) => {
  questionList.value.splice(index, 0, {
    title: "",
    options: [],
  });
};

/**
 * 删除题目
 * @param index
 */
const deleteQuestion = (index: number) => {
  questionList.value.splice(index, 1);
};

/**
 * 添加题目选项
 * @param question
 * @param index
 */
const addQuestionOption = (question: API.QuestionContentDTO, index: number) => {
  if (!question.options) {
    question.options = [];
  }
  question.options.splice(index, 0, {
    key: "",
    value: "",
  });
};

/**
 * 删除题目选项
 * @param question
 * @param index
 */
const deleteQuestionOption = (
  question: API.QuestionContentDTO,
  index: number
) => {
  if (!question.options) {
    question.options = [];
  }
  question.options.splice(index, 1);
};

// 提交按钮是否加载中
const submitButtonIsLoading = ref(false);

/**
 * 提交题目给后台
 */
const doSubmit = async () => {
  submitButtonIsLoading.value = true;

  let result;
  if (oldQuestionVO.value?.id !== undefined) {
    // 题目存在, 调用编辑题目接口
    result = await editQuestionUsingPost({
      id: oldQuestionVO.value?.id,
      questionContent: questionList.value,
    });
  } else {
    // 题目不存在, 调用新增题目接口
    result = await addQuestionUsingPost({
      appId,
      questionContent: questionList.value,
    });
  }

  // 提交题目给后台
  if (result.data.code === ResponseCodeEnum.SUCCESS) {
    ElMessage.success("题目编辑提交成功");
    ElMessage.warning("注: 题目修改后, 应用会重新变为 \"审核中\" 状态")

    // 将得到的 appId 赋值给 oldQuestionVO.value.id, 这样多次点击提交就不报错
    if (!oldQuestionVO.value?.id) {
      oldQuestionVO.value = {
        id: result.data.data as number,
      };
    }

  } else {
    ElMessage.error("提交失败: " + result.data.message);
  }

  submitButtonIsLoading.value = false;
};

// dialog 是否可见
const dialogFormVisible = ref(false);

// 生成按钮是否加载中
const aiGenerateButtonLoading = ref(false);

// dialog 中的表格
const aiGenerateQuestionForm = ref<API.AiGenerateQuestionRequest>({
  appId,
  questionNumber: 1,
  optionNumber: 2,
});

// 当前已 AI 生成的题目数量
const aiGeneratedQuestionNumber = ref(0);

/**
 * AI 生成题目
 */
const doAiGenerateQuestions = async () => {
  aiGenerateButtonLoading.value = true;

  // 创建 SSE 请求
  const eventSource = new EventSource(
    "http://charles.wow.sh.cn/zhifou/question/ai_generate/sse?" +
    `appId=${aiGenerateQuestionForm.value.appId}` +
    `&questionNumber=${aiGenerateQuestionForm.value.questionNumber}` +
    `&optionNumber=${aiGenerateQuestionForm.value.optionNumber}`,
  )

  // 接收消息
  eventSource.onmessage = event => {
    // 将题目加到题目列表中
    const questionDataGenerated: API.QuestionContentDTO = JSON.parse(event.data);
    questionList.value.push(questionDataGenerated);
    aiGeneratedQuestionNumber.value++;
  };

  // 报错或连接关闭时触发
  eventSource.onerror = event => {
    if (event.eventPhase === EventSource.CLOSED) {
      ElMessage.success("生成完毕");
    } else {
      ElMessage.error("生成失败");
    }

    eventSource.close();
    aiGeneratedQuestionNumber.value = 0;

    // 在流结束的时候再关闭加载效果
    aiGenerateButtonLoading.value = false;
  };
};


</script>

<style scoped lang="less">
#addQuestionPage {
  padding: 20px;
  width: 60%;
  margin: 0 auto;
}

.el-form {
  width: 100%;
}

.el-form-item,
.el-form-item .el-form-item {
  margin-bottom: 10px;
}

.el-form-item:last-child {
  margin-bottom: 5px;
}

.questionItem {
  padding: 10px;
  border: 1px solid rgb(220, 223, 230);
}

.submitButton {
  width: 150px;
  margin-top: 10px;
}

.addOnTopButton {
  margin-bottom: 10px;
}

.invisible {
  visibility: hidden;
}

.progressWrapper {
  width: 100%;

  .el-progress {
    margin-top: 20px;
    margin-bottom: 5px;
    width: 100%;
  }
}

.dialog-footer .el-button {
  width: 100px;
}
</style>